﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufQtObjectPtr.h"

class QDrag;
class QWidget;
class QPoint;
class QDragEnterEvent;
class QDragMoveEvent;
class QDropEvent;

namespace gnuf {
    class Item;
    class ArrangementAreaContent;

    class GNUF_BASE_EXPORT DragMove final
    {
    public:
        enum EDropTarget : std::uint8_t
        {
            eAnyplace               = 1 << 0,
            eArrangementAreaContent = 1 << 1
        };
        static gcmp::OwnerPtr<DragMove> make(Item * dragSource, std::uint8_t dropTarget);

    private:
        DragMove(Item *, QWidget *, std::uint8_t);
    public:
        ~DragMove();

        static DragMove * current();
        
        // Convenient methods to handle dragging and moving.
        static bool onQtDragEnterEvent(QWidget *, QDragEnterEvent *);
        static bool onQtDragMoveEvent(QWidget *, QDragMoveEvent *);
        static bool onQtDropEvent(QWidget *, QDropEvent *);

        Item * dragSource() const { return m_dragSource; }
        std::uint8_t dropTarget() const { return m_dropTarget; }
        ArrangementAreaContent * pendingContent() const { return m_pendingContent; }
        ArrangementAreaContent * drappableContent() const { return m_drappableContent; }

        typedef std::function<void(DragMove *)> Callback;

        void setOnDrop(const DragMove::Callback & onDrop) { m_onDrop = onDrop; }
        const DragMove::Callback & onDrop() const { return m_onDrop; }

        typedef std::function<void(std::wstring &, std::map<std::wstring, std::wstring> &)> Callback2;

        void setOnRecordJournal(const DragMove::Callback2 & onRecordJournal) { m_onRecordJournal = onRecordJournal; }
        const DragMove::Callback2 & onRecordJournal() const { return m_onRecordJournal; }

        void setOwnerless() { m_ownerless = true; }
        bool ownerless() const { return m_ownerless; }

        void setDragCursor(const std::wstring& iconPath);
        void setHotSpot(const QPoint& pt, bool transferToSourceTargetLocal);
        void overrideRepretationPixmap(const std::wstring& iconPath);

        void appendRepretation(const std::wstring & filePath);

        void run();
        
        void moveTo(int globalX, int globalY);
        void drop();

    private:
        Item * m_dragSource;
        const std::uint8_t m_dropTarget;
        DragMove::Callback m_onDrop;
        DragMove::Callback2 m_onRecordJournal;
        bool m_ownerless;
        gcmp::QtAutoPtr<QDrag> m_qtDrag;
        ArrangementAreaContent * m_drappableContent, * m_pendingContent;
    };
}
